package com.example.demo.use_demo.a_remote_service;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpConfig;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.example.demo.person.vo.PersonVO;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@Slf4j
@Component
public class RemoteSync {

    public static void main1(String[] args) throws IOException {
//        HttpRequest request = HttpUtil.createGet("https://fastly.picsum.photos/id/11/200/300.jpg?grayscale&hmac=AbWDZhKcI8M0nP8SI0CJgazVLjf7IqItNhjxGBUrUXI");
//        HttpResponse httpResponse = request.executeAsync();
//        InputStream inputStream = httpResponse.bodyStream();
//
//        File file = new File("D:/files/1/zzz.jpg");
//        FileUtils.copyInputStreamToFile(inputStream,file);
        List<SyncFile> video = syncFiles(new ArrayList<>(), "video");
        log.info(">>>>>>>>>>");
    }

    @Data
    public static class SyncFile{
        private String fileName;
        private Long fileSize;
        private String remoteUrl;
        private String systemUul;
    }

    public static List<SyncFile> syncFiles(List<String> downloadFileUrls, String fileType){
        downloadFileUrls .add("https://fastly.picsum.photos/id/11/200/300.jpg?grayscale&hmac=AbWDZhKcI8M0nP8SI0CJgazVLjf7IqItNhjxGBUrUXI");

        String serverPath = "D:/files/";
        String fileTypePath = StrUtil.isBlank(fileType) ? StrUtil.EMPTY : fileType + "/";
        String dateStrPath = DateUtil.format(DateTime.now(), "yyyyMMdd") + "/";
        String fileDirPath = serverPath + fileTypePath + dateStrPath;

        List<SyncFile> syncFiles = new ArrayList<>();
        downloadFileUrls.forEach(downloadFileUrl-> {
            try {
                HttpRequest request = HttpUtil.createGet(downloadFileUrl);
                request.timeout(60*1000);
                // 下载文件
                HttpResponse response = request.executeAsync();
                InputStream inputstream = response.bodyStream();
                //保存到本地目录
                String fileName = "https://fastly.picsum.photos/id/11/200/301.jpg".substring(downloadFileUrl.lastIndexOf("/")+ 1);
                String filePath = fileDirPath + fileName;
                File file = new File(filePath);
                FileUtils.copyInputStreamToFile(inputstream,file);

                SyncFile syncFile = new SyncFile();
                syncFile.setFileName(fileName);
                syncFile.setFileSize(response.contentLength());
                syncFile.setRemoteUrl("https://fastly.picsum.photos/id/11/200/300.jpg");
                syncFile.setSystemUul(filePath);
                syncFiles.add(syncFile);
            } catch (Exception e){
                log.error("Exception",e);
            }
        });
        return syncFiles;
    }

    //-----------------------------------------------------------------------------------------------------
    @Qualifier("taskExecutor")
    @Autowired
    private ThreadPoolTaskExecutor executor;

    private static final int RETRY_TIMES = 3;
    private static final String SZWB_TOKEN_EXPIRED_MSG = "Token无效或过期";
    private static final String IMAGE_DIR_PATH = "D:/files/image/award/";
    private List<SsgwAward> awards = new ArrayList<>();

    public void syncAward() {
        // 步骤1 同步获奖数据
        String token = this.syncAwardData();
        // 步骤2 同步图片下载地址
        this.syncAwardImageUrl(token);
        // 步骤3 同步图片
        this.syncAwardImage();
    }

    /**
     * 同步荣誉基础数据
     */
    public String syncAwardData() {
        // 获取token
        String token = this.getSzwbToken();
        if(token == null){
            return null;
        }
        // 获取荣誉数据
        JSONObject awardDataJsonTemp = this.getAwardDatas(1, 200,token);
        int totalPages = awardDataJsonTemp.getIntValue("pages");
        int currentPage = 1;
        while (currentPage <= totalPages){
            JSONObject awardDataJson = currentPage == 1 ? awardDataJsonTemp : getAwardDatas(currentPage, 200,token);
            currentPage++;
            if(awardDataJson == null){
                continue;
            }
            JSONArray awardJsonArray = awardDataJson.getJSONArray("records");
            if(CollectionUtil.isEmpty(awardJsonArray)){
                continue;
            }
            // 数据组装
            List<SsgwAward> awards  = new ArrayList<>();
            List<JSONObject> jsonObjects = awardJsonArray.toList(JSONObject.class);
            jsonObjects.forEach(awardJson -> {
                SsgwAward ssgwAward = new SsgwAward();
                ssgwAward.setId(awardJson.getString("id"));
                ssgwAward.setAwardName(awardJson.getString("file_title"));
                ssgwAward.setImage(awardJson.getString("id"));
                awards.add(ssgwAward);
            });
            // 数据保存(ID保持和源数据一致，因为保存图片的时候生成的名称是唯一且随机的)
            System.out.println("保存数据" + awards.size() + "条");
            this.awards = awards;
        }
        return token;
    }

    /**
     * 分页查询数据
     * design_point - 设计亮点
     * quality_prize - 质量将
     * honor_company - 中心
     * award_company_level - 获奖等级
     * file_title - 奖项名称
     * docIds - 获奖照片
     * prize_category - 获奖类型
     * project_important_prize - 项目重要奖项
     * award_date - 获奖日期
     * security_prize - 安全奖
     * important_design_award - 重要设计奖项
     * id - ID
     * bim_prize_name - BIM技术应用奖
     * bim_prize_rank - BIM奖项类别
     * pro_name - 项目名称
     * crrc_pro_num - 项目编码
     */
    public JSONObject getAwardDatas(int currentPage, int pageSize, String token){
        // 分页查询数据(重试3次)
        int attemptTimes = 0;
        JSONObject awardDataJson = null;
        while (awardDataJson == null && attemptTimes < RETRY_TIMES){
            HttpRequest awardDataRequest = HttpUtil.createPost("https://szwb.sz.gov.cn:9814/eim/api/fileCollect/prizeData/szgws/getData");
            awardDataRequest.header("Authorization","Bearer " + token);
            awardDataRequest.form("currentPage",currentPage);
            awardDataRequest.form("pageSize",pageSize);
            HttpResponse awardDataResponse = awardDataRequest.execute();
            if(awardDataResponse != null && awardDataResponse.isOk()){
                JSONObject awardDataResponseJson = JSONObject.parseObject(awardDataResponse.body());
                if(awardDataResponseJson != null){
                    if("y".equals(awardDataResponseJson.getString("status"))){
                        awardDataJson = awardDataResponseJson.getJSONObject("data");
                    } else if(SZWB_TOKEN_EXPIRED_MSG.equals(awardDataResponseJson.getString("msg"))){
                        // 如果是token过期则重新获取
                        token = this.getSzwbToken();
                    }
                }
            }
            attemptTimes++;
        }
        return awardDataJson;
    }

    /**
     * 同步荣誉数据相关获奖图片下载地址（根据荣誉数据ID查询荣誉相关获奖图片下载地址）
     */
    public void syncAwardImageUrl(String existToken){
        // 获取token
        String token = existToken == null ? this.getSzwbToken() : existToken;
        if(token == null){
            return;
        }
        // 获取图片下载地址
        List<List<SsgwAward>> toGetImageUrlAwards = CollectionUtil.split(this.awards,10);
        for(List<SsgwAward> awardsTemp : toGetImageUrlAwards){
            int attemptTimes = 0;
            JSONArray imageDataJson = null;
            while (imageDataJson == null && attemptTimes < RETRY_TIMES){
                HttpRequest awardImageUrlRequest = HttpUtil.createPost("https://szwb.sz.gov.cn:9814/eim/api/fileCollect/prizeData/szgws/getDoc");
                awardImageUrlRequest.header("Authorization","Bearer " + token);
                awardImageUrlRequest.form("fileIds",awardsTemp.stream().map(SsgwAward::getId).collect(Collectors.joining(StrUtil.COMMA)));
                awardImageUrlRequest.form("docIds",StrUtil.EMPTY);
                awardImageUrlRequest.form("base64Flag",false);
                HttpResponse imageDataResponse = awardImageUrlRequest.execute();
                if(imageDataResponse != null && imageDataResponse.isOk()){
                    JSONObject imageDataResponseJson = JSONObject.parseObject(imageDataResponse.body());
                    if(imageDataResponseJson != null){
                        if("y".equals(imageDataResponseJson.getString("status"))){
                            imageDataJson = imageDataResponseJson.getJSONArray("data");
                        } else if(SZWB_TOKEN_EXPIRED_MSG.equals(imageDataResponseJson.getString("msg"))){
                            // 如果是token过期则重新获取
                            token = this.getSzwbToken();
                        }
                    }
                }
                attemptTimes++;
            }
            if(imageDataJson == null){
                continue;
            }
            // 数据组装
            List<JSONObject> jsonObjects = imageDataJson.toList(JSONObject.class);
            Map<String, List<JSONObject>> groupByOwnerId = jsonObjects.stream().collect(Collectors.groupingBy(i -> i.getString("ownerId")));
            awardsTemp.forEach(awardTemp -> {
                List<JSONObject> jsonObjectsTemp = groupByOwnerId.get(awardTemp.getId());
                if(CollectionUtil.isNotEmpty(jsonObjectsTemp)){
                    List<JSONObject> downloadUrls = jsonObjectsTemp.stream().map(i -> {
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("downloadUrl",i.getString("downloadUrl"));
                        jsonObject.put("fileType",i.getString("fileType"));
                        jsonObject.put("id",i.getString("id"));
                        return jsonObject;
                    }).collect(Collectors.toList());
                    awardTemp.setImage(JSONObject.toJSONString(downloadUrls));
                } else {
                    awardTemp.setImage(null);
                    log.info("ownerId -> {}", awardTemp.getId());
                }
            });
            // 分批更新可以
            log.info("获取图片下载地址更新" + awardsTemp.size() + "条");
        }
        // 数据更新
        this.awards = toGetImageUrlAwards.stream().flatMap(List::stream).collect(Collectors.toList());
        log.info(">>>>>>>>>>>获取图片下载地址更新共" + this.awards.size() + "条");
    }

    @Autowired
    private CloseableHttpClient httpClient;
    /**
     * 同步荣誉数据相关图片
     */
    public void syncAwardImage(){
        // 下载图片(查询imageDownloadUrls不为空且包含http关键字的数据)
        List<SsgwAward> toDownloadImageAwards = this.awards.stream().filter(i -> StrUtil.isNotBlank(i.getImage())).collect(Collectors.toList());
        List<List<SsgwAward>> toDownloadImageAwardsSplit = CollectionUtil.split(toDownloadImageAwards, 10);
        for(List<SsgwAward> toDownloadImageAwardsTemp : toDownloadImageAwardsSplit){
            List<CompletableFuture<Void>> futures = new ArrayList<>();
            toDownloadImageAwardsTemp.forEach(awardTemp -> {
                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                    String imageDownloadUrls = awardTemp.getImage();
                    JSONArray imageDownloadUrlJsonArray = JSONArray.parse(imageDownloadUrls);
                    List<JSONObject> imageDownloadUrlJsons = imageDownloadUrlJsonArray.toList(JSONObject.class);
                    for(JSONObject imageDownloadUrlJson : imageDownloadUrlJsons){
                        int attemptTimes = 0;
                        String fileName = null;
                        while(fileName == null && attemptTimes < RETRY_TIMES){
                            String downloadUrl = imageDownloadUrlJson.getString("downloadUrl");
                            String fileType = imageDownloadUrlJson.getString("fileType");
                            String id = imageDownloadUrlJson.getString("id");
                            HttpRequest imageRequest = HttpUtil.createGet(downloadUrl);
                            HttpResponse imageResponse = imageRequest.executeAsync();
                            if(imageResponse != null && imageResponse.isOk()){
                                log.info("线程:" + Thread.currentThread().getName() + "    " + fileType + "图片下载成功!");
                                InputStream inputstream = imageResponse.bodyStream();
                                //保存到本地目录
                                String dateNow = DateUtil.format(DateTime.now(), DatePattern.PURE_DATE_FORMAT);
                                fileName = id + StrUtil.DOT + fileType;
                                String filePath = IMAGE_DIR_PATH + fileName;

                                File file = new File(filePath);
                                try {
                                    FileUtil.writeFromStream(inputstream,file);
                                } catch (IORuntimeException e) {
                                    fileName = null;
                                    log.error("图片保存失败",e);
                                }
                            }
                            attemptTimes++;
                        }
                        String imageNames = awardTemp.getImage();
                        awardTemp.setImage(StrUtil.isBlank(imageNames) ? fileName : (fileName == null ? imageNames : imageNames + StrUtil.COMMA + fileName));
                    }
                },executor);
                futures.add(future);
            });
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
            log.info("下载图片" + toDownloadImageAwardsTemp.size() + "张");
            // 数据更新
            this.awards = toDownloadImageAwardsTemp;
        }
    }

    @Data
    private static class SsgwAward {
        private String id;
        private String awardName;
        private String image;
    }

    /**
     * 获取token
     */
    public String getSzwbToken(){
        // 获取token(重试3次)
        int attemptTimes = 0;
        String token = null;
        while (token == null && attemptTimes < RETRY_TIMES){
            String tokenResponseStr = HttpUtil.post("https://szwb.sz.gov.cn:9814/eim/oauth/token?client_id=szgwsPrizeData&client_secret=c25cb3809f2e407981f8af1a95f07278&grant_type=client_credentials", (String) null);
            JSONObject tokenResponseJson = JSONObject.parseObject(tokenResponseStr);
            if(tokenResponseJson != null && "y".equals(tokenResponseJson.getString("status"))){
                token = tokenResponseJson.getJSONObject("data").getString("access_token");
            }
            attemptTimes++;
        }
        return token;
    }
}
